#!/usr/bin/python3
import gc
import os

from openpyxl import load_workbook

from .Base_Plugin import Base_Plugin
from utils import String_Util


class Entity_Field:
    """
    实体属性
    """

    def __init__(
        self,
        entity_name: str,
        column_name: str,
        sql_type: str,
        comment: str,
        not_null: str,
        single_verify: str,
        i18n: str,
        unique: str,
        currency: str,
    ) -> None:
        self.entity_name: str = entity_name
        self.column_name: str = column_name
        self.sql_type: str = sql_type
        self.name: str = String_Util.field_name(self.column_name)
        self.comment: str = String_Util.check_comment_symbol(comment)
        self.not_null: bool = not_null == "Y"
        self.single_verify: bool = single_verify == "Y"
        self.i18n: bool = i18n == "国际化名称"
        self.unique: bool = unique == "Y"
        self.currency: bool = currency == "金额"

        self.typescript_type = (
            "I18NName"
            if self.i18n
            else (
                "Currency"
                if self.currency
                else (
                    "number"
                    if sql_type in ["bigint", "int"]
                    else (
                        "boolean"
                        if "bit" in sql_type
                        else "Date" if "datetime" in sql_type else "string"
                    )
                )
            )
        )

    def ignore(self, ignore_list=None):
        if ignore_list is not None:
            return self.name in ignore_list
        else:
            return self.name in String_Util.ignore_fields

    def required(self):
        return self.not_null

    def is_sort(self):
        if self.column_name == "sort_number":
            return True
        else:
            return False

    def is_status(self):
        if self.column_name == "status":
            return True
        else:
            return False

    def is_single_verify(self):
        return self.single_verify

    def code_field(self):
        name = self.name
        typescript_type = self.typescript_type
        return f"""{name}?: {typescript_type};"""

    def code(self):
        return self.code_field()


class Entity:
    """
    实体模型
    """

    def __init__(self, author, package: str, table_name: str, comment: str) -> None:
        self.author = author
        self.package = package
        self.table_name = table_name
        self.name = String_Util.entity_name(self.table_name)
        self.comment = String_Util.check_comment_symbol(comment)
        self.fields: list[Entity_Field] = list()
        self.prefix = self.table_name.split("_")[0].lower()
        self.sort_number = False

    def has_sort(self):
        for field in self.fields:
            if field.ignore():
                continue
            if field.is_sort():
                return True
        return False

    def has_status(self):
        for field in self.fields:
            if field.ignore():
                continue
            if field.is_status():
                return True
        return False

    def has_single_verify(self):
        for field in self.fields:
            if field.ignore():
                continue
            if field.is_single_verify():
                return True
        return False

    def code_includes(self):
        i18n = False
        currency = False
        for field in self.fields:
            if field.ignore():
                continue
            code = field.code()
            if "private NameInfo" in code:
                i18n = True
            if "private Currency" in code:
                currency = True

        includes = list()

        if i18n:
            includes.append(f"""I18NName""")
        if currency:
            includes.append(f"""Currency""")

        includes = ",".join(includes)
        return includes

    def code_fields(self):
        field_code = list()
        for field in self.fields:
            if field.ignore():
                continue
            code = field.code()
            code = f"""
    /**
     * {field.comment}
     */
     {code}"""
            field_code.append(code)
        field_code = "\r".join(field_code)
        return field_code

    def save_file(self, dir):
        _target_dir = os.path.join(dir, self.context["code_storage"]["root"], "entity")
        if not os.path.exists(_target_dir):
            os.makedirs(_target_dir)
        with open(
            os.path.join(_target_dir, "{}.ts".format(self.name)),
            mode="w",
            encoding="utf-8",
        ) as f:
            f.write(self.code())

    def add_fields(self, fields: list):
        self.fields.extend(fields)
        for field in fields:
            if "sort_number" == field.column_name:
                self.sort_number = True

    def code(self):
        author = self.author
        package = self.package
        prefix = self.prefix
        table_name = self.table_name.lower()
        name = self.name
        comment = self.comment

        includes = self.code_includes()
        if len(includes) > 0:
            includes = f"""import type { includes } from "./interfaces";"""

        fields = self.code_fields()

        return f"""
{includes}

type {name} = {"{"}
{fields if len(fields) > 0 else ''}
{"}"}
"""


class Generate_Web_Admin_Code(Base_Plugin):
    """
    生成PC前端管理系统代码
    """

    def __init__(self, context) -> None:
        super().__init__()
        self.context = context

    def get_fields(self, entity_name, sheet):
        entity_fields = list()
        for row in sheet.rows:
            if row[0].row < self.project_config["列字段开始行"]:
                continue

            entity_fields.append(
                Entity_Field(
                    entity_name=entity_name,
                    column_name=row[1].value,
                    sql_type=row[2].value,
                    comment=row[6].value,
                    not_null=row[3].value,
                    single_verify=row[7].value,
                    i18n=row[8].value,
                    unique=row[4].value,
                    currency=row[8].value,
                )
            )
        return entity_fields

    def run(self, workspace, source):
        author = self.context["author"]
        package = self.context["package"]
        workbook = load_workbook(os.path.join(workspace, source))
        _directory = workbook["目录"]
        _lookup_type = workbook["数据字典组"]
        _lookup_item = workbook["数据字典项"]
        # lookups = self.get_lookups(_lookup_type, _lookup_item)

        _target_path = os.path.join(workspace, self.context["code_config"], "web")
        if not os.path.exists(_target_path):
            os.mkdir(_target_path)

        if not os.path.exists(_target_path):
            os.mkdir(_target_path)

        for row in _directory.rows:
            if row[0].value == "序号":
                continue
            if row[1].value is None:
                break
            entity = Entity(author, package, row[1].value, row[2].value)
            entity.add_fields(self.get_fields(entity.name, workbook[row[2].value]))
            entity.save_file(_target_path)
        del workbook
        gc.collect()
        return source
